路徑(Path)是指圖中的一個序列,其中連接相鄰節點的邊構成了一條路徑。路徑可以用來表示從一個節點到另一個節點的過程,並通常用來解決許多不同的問題,例如尋找兩個節點之間的路徑、檢測圖中是否存在特定類型的路徑等。
其中,最短路徑(Shortest Path)問題是圖論中一個常見的挑戰,其目標是找到圖中兩個節點之間的最短路徑。這個最短路徑可以按不同標準來衡量,如權重最小、權重最大、或者經過的邊或節點數最少等。
最長路徑問題是最短路徑問題的一個變體。在最長路徑問題中,你的目標是找到圖中兩個節點之間的最長路徑,而這個最長路徑是通過給每條邊的權重取負值來找到的。換句話說,最長路徑問題可以轉化為一個最短路徑問題,只需將所有邊的權重取相反數,然後使用最短路徑演算法來找到最短路徑,即可得到最長路徑。
以最短路徑問題為例,有幾種相關的演算法可供選擇,以應對不同情境:
這些演算法提供了不同的方法,可根據具體問題的性質和圖的特點來選擇適當的解決方案。最短路徑問題在路線規劃、網絡優化、通信網絡等領域有廣泛的應用。
具體步驟如下:

const int INF = numeric_limits<int>::max();
class Graph {
private:
    int vertices, edges; // 點的個數, 邊的個數
    vector<vector<int>> adjMatrix; // 鄰接矩陣
    vector<bool> visited; // 該點是否被訪問過
    vector<int> distance; // 路徑長度
    queue<pair<char,int >> shortPath; // 最短路徑
public:
    Graph(int vertices) : vertices(vertices) {
        edges = 0;
        adjMatrix.resize(vertices);
        for (int i = 0; i < vertices; i++) {
            adjMatrix[i].resize(vertices, 0);
        }
        visited.resize(vertices, false);
        distance.resize(vertices, INF); // 初始化距離為無限大
    }
    
    void addEdge(char from, char to, int weight) {
        adjMatrix[from - 'A'][to - 'A'] = weight;
        edges++;
    }
    
    int minKey() { // 找到最小權重的點
        int min = INF, minIndex=-1;
        for (int v = 0; v < vertices; v++) {
            if (visited[v] == false && distance[v] < min) {
                min = distance[v];
                minIndex = v;
            }
        }
        return minIndex;
    }
    
    void dijkstra(char start) {
        distance[start - 'A'] = 0;
        for (int i = 0; i < vertices ; i++) { // 次數
            int u = minKey();// 找到最小權重的點
            visited[u] = true;
            shortPath.push(make_pair(u+'A',distance[u]));
            for (int v = 0; v < vertices; v++) { // 更新最小權重的點的鄰接點
                if (!visited[v]){ // 如果該點沒有被訪問過
                    // 新的路徑 < 舊的路徑 => 更新路徑
                    if(adjMatrix[u][v] &&  distance[u] + adjMatrix[u][v] < distance[v]){
                        distance[v] = distance[u] + adjMatrix[u][v];
                    }
                }
            }
        }
    }
    void printShortPath(){
        while(!shortPath.empty()){
            cout << shortPath.front().first << ' ' << shortPath.front().second << endl;
            shortPath.pop();
        }
    }
};
具體步驟如下:

const int INF = numeric_limits<int>::max();
class Graph { // 圖的結構
private : 
    int vertices, edges; // 點的個數, 邊的個數
    vector<vector<pair<int,int>>> adjMatrix; // 鄰接矩陣 <點,權重>
    vector<int> distance; // 路徑長度
public:
    Graph(int vertices) : vertices(vertices) { // 初始化
        edges = 0;
        adjMatrix.resize(vertices);
        distance.resize(vertices, INF); // 初始化距離為無限大
    }
    void addEdge(char from, char to, int weight) { // 加邊
        adjMatrix[from - 'A'].push_back({to - 'A',weight});
        edges++;
    }
    void printShortPath() { // 印出最短路徑
        cout << "Shortest Path: " << endl;
        for(int i = 0 ; i < vertices ; i++){
            cout << char(i+'A') << ": " << distance[i] << endl;
        }
    }
    void bellmanFord(char start){ //DP 演算法
        distance[start - 'A'] = 0; // 起點的權重為0
        // 遍歷所有點
        for (int i = 0; i < vertices ; i++) { // 需要遍歷的次數為點的個數\
            // 每次遍歷都會更新一次最短路徑
            for(int u = 0 ; u < vertices ; u++){ // 遍歷所有點
                for(auto v : adjMatrix[u]){ // 遍歷所有鄰接點
                    // 新的路徑 < 舊的路徑 => 更新路徑
                    if(distance[u] != INF ){
                        distance[v.first] = min(distance[v.first], distance[u] + v.second);
                    }
                }
            } // O(E)
        } // O(V*E)
        
    }
};
| 特性 | Dijkstra's Algorithm | Bellman-Ford Algorithm | 
|---|---|---|
| 最短路徑類型 | 單一源最短路徑 | 單一源最短路徑 | 
| 適用圖類型 | 無負權重邊,有向或無向 | 有向或無向,可含負權重邊 | 
| 時間複雜度 | O(V^2) 或 O(Vlog(V)) | O(VE) | 
| 優點 | 處理正權重邊快速 | 處理負權重邊 | 
| 缺點 | 不適用負權重邊 | 較低效率 | 
| 典型應用 | 網絡路由 | 金融建模 | 
總結,Dijkstra's Algorithm適用於無負權重邊的單一源最短路徑問題,但不適用於負權重邊。Bellman-Ford Algorithm能處理帶負權重邊的單一源最短路徑,並檢測負權重環路,但效率較低。因此,選擇演算法應基於具體問題的要求和圖的特性。
每個人都有自己的節奏,不需要因為別人會的事情而勉強自己,也不必追求無止境的完美或頂尖。我們不必應付所有事情,也不必將所有知識都吸收。重要的是要了解自己需要的和想要的是什麼。